package com.threegroup.admin.service;

import co.elastic.clients.elasticsearch.ingest.simulate.Document;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmCallback;
import com.threegroup.admin.dao.DishEntityMapper;
import com.threegroup.admin.dao.DishFlavorEntityMapper;
import com.threegroup.admin.dto.DishDTO;
import com.threegroup.admin.entity.DishEntity;
import com.threegroup.admin.entity.DishFlavorEntity;
import com.threegroup.admin.exception.TakeOutException;
import com.threegroup.admin.utils.AssertUtil;

import com.threegroup.admin.utils.RabbitMqSend;
import com.threegroup.common.utils.Result;
import com.threegroup.common.validator.AssertUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class DishService {
    @Resource
    private DishEntityMapper dishEntityMapper;
    @Resource
    private DishFlavorEntityMapper dishFlavorEntityMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    public static Integer TIME_OUT_CACHE = 60 * 60 * 24;
    @Resource
    private ElasticsearchRestTemplate restTemplate;


    @Transactional(propagation = Propagation.REQUIRED)
    public void saveDish(DishDTO dishDTO) {
        //校验菜品信息非空
        checkDishParams(dishDTO);
        //校验逻辑 菜品名非重
        DishEntity dishEntity = dishEntityMapper.queryDishByName(dishDTO.getName());
        AssertUtil.isTrue(dishEntityMapper.queryDishByName(dishDTO.getName()) != null, 302, "菜品名称已存在，请重新输入");
        //默认参数添加到Dish类
        dishDTO.setStatus(1);
        dishDTO.setCode("");
        dishDTO.setCreateDate(new Date());
        dishDTO.setUpdateDate(new Date());
        dishDTO.setIsDeleted(0);
        dishDTO.setSort(0);

        //执行菜品添加
        AssertUtil.isTrue(dishEntityMapper.insertSelectiveDisdto(dishDTO) != 1, 303, "添加失败请重试");

        //成功就同步到Es
        System.out.println("同步到ES开始："+dishDTO);
        String s = JSON.toJSONString(dishDTO);
        RabbitMqSend.SynchSendMessage(s);
        System.out.println("同步到ES结束：");


        //由于要添加口味信息，需要xml文件开启主键返回
        Long dishDTOIdid = dishDTO.getId();


        //如果有口味信息，进行判断
        List<DishFlavorEntity> flavors1 = dishDTO.getFlavors();

        if (flavors1 != null) {//有口味信息
            //获取口味信息
            for (DishFlavorEntity flavors : flavors1) {
                if (flavors != null) {
                    //校验口味信息非空
                    AssertUtils.isBlank(flavors.getName(), 302, "口味名不能为空");
                    AssertUtils.isBlank(flavors.getValue(), 302, "口味内容不能为空");
                    //默认信息添加
                    flavors.setCreateDate(new Date());
                    flavors.setCreator(dishDTO.getCreator());
                    flavors.setUpdateDate(new Date());
                    flavors.setUpdater(dishDTO.getCreator());
                    flavors.setDishId(dishDTOIdid);
                    flavors.setIsDeleted(0);
                    flavors.setValue("[" + flavors.getValue() + "]");//value格式更改
                    //执行口味添加
                    AssertUtil.isTrue(dishFlavorEntityMapper.insertSelective(flavors) != 1, 303, "添加失败请重试");

                }
            }

        }


    }

    /**
     * 校验非空
     *
     * @param dishDTO
     */
    private void checkDishParams(DishDTO dishDTO) {

        AssertUtils.isBlank(dishDTO.getName(), 302, "菜品名称不能为空");
        AssertUtils.isNull(dishDTO.getCategoryId(), 302, "菜品分类不能为空");
//        AssertUtils.isNull(dishDTO.getCreator(), 302, "创建人不能为空");
        AssertUtils.isNull(dishDTO.getPrice(), 302, "菜品价格不能为空");
        AssertUtils.isNull(dishDTO.getImage(), 302, "图片不能为空");
//        AssertUtil.isTrue(StringUtils.isBlank(dishDTO.getCode()),"菜品码不能为空");
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void updateDish(DishDTO dishDTO) {
        Long dishDTOId = dishDTO.getId();
        AssertUtils.isNull(dishDTOId, 303, "待更新信息不存在");
        //校验其他参数非空
        checkDishParams(dishDTO);
        AssertUtils.isNull(dishDTO.getUpdater(), 303, "更新者不能为空");


        //校验名字唯一性
        DishDTO dishDTO1 = dishEntityMapper.queryDishByNameNoId(dishDTO);
        AssertUtil.isTrue(dishDTO1 != null, 303, "菜品名已存在，请重新输入");
        //参数默认设置
        dishDTO.setUpdateDate(new Date());
        //执行更新
        AssertUtil.isTrue(dishEntityMapper.updateByPrimaryKeySelectiveDIshDto(dishDTO) != 1, 303, "更新失败请重试");
        //同步到Es
        String s = JSON.toJSONString(dishDTO);
        System.out.println("更新到ES开始："+s);
        RabbitMqSend.SynchSendMessage(s);
        System.out.println("更新到ES结束：");

        //执行更新口味信息
        //判断原来数据库是否有口味信息
        List<DishFlavorEntity> dishFlavorEntity = dishFlavorEntityMapper.queryDishFlavorByDishId(dishDTOId);
        List<DishFlavorEntity> flavors = dishDTO.getFlavors();//获取传入的口味信息
        //原来有,先删除口味信息
        if (dishFlavorEntity != null && dishFlavorEntity.size() != 0) {
            int size = dishFlavorEntity.size();
            int i = dishFlavorEntityMapper.deleteByDishId(dishDTOId);
            AssertUtil.isTrue( i!= size, 303, "更新失败");
        }
        //传入的口味信息不是空？
        if (flavors != null && flavors.size() != 0 ) {
            ////添加口味信息操作
            //参数校验非空
            for (DishFlavorEntity flavor : flavors) {
                //校验口味信息非空
                AssertUtil.isTrue(StringUtils.isBlank(flavor.getName()), 302, "口味名不能为空");
                AssertUtil.isTrue(StringUtils.isBlank(flavor.getValue()), 302, "口味内容不能为空");
//                AssertUtil.isTrue(flavor.getUpdater() == null, 302, "更新者不能为空");
                //把传入的额参数赋值给查出来的
                flavor.setIsDeleted(0);
                flavor.setUpdateDate(new Date());//更新时间
                flavor.setCreateDate(new Date());//创建时间
                flavor.setUpdater(dishDTO.getUpdater());//更新者
                flavor.setCreator(dishDTO.getCreator()==null?dishDTO.getUpdater():dishDTO.getCreator());//获取创建者
//                flavor.setCreateDate(new Date());//设置新的创建时间
                flavor.setDishId(dishDTOId);//填充该菜品的Id
//                flavor.setValue("[" + flavor.getValue() + "]");//value格式更改
                AssertUtil.isTrue(dishFlavorEntityMapper.insertSelective(flavor) != 1, 303, "更新失败");
            }
        }
    }

    /**
     * 删除菜品
     *
     * @param ids
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteDish(List<String> ids)  {
        //遍历字符数组，检查dishId存在
        for (String id : ids) {
            Long aLong = Long.valueOf(id);
            AssertUtils.isNull(aLong, 302, "待删除对象不存在");
            DishDTO dishDTO = dishEntityMapper.queryDishById(aLong);
            AssertUtils.isNull(dishDTO, 302, "待删除对象不存在");
            //执行删除
            //菜品删除
            AssertUtil.isTrue(dishEntityMapper.deleteDishById(aLong) != 1, 303, "删除失败");

            //同步到ES
            //多删除实际是更新状态码
            dishDTO.setStatus(0);
            dishDTO.setIsDeleted(1);
            System.out.println(dishDTO);
            restTemplate.save(dishDTO);
            //使用消息队列
//            String s = JSON.toJSONString(dishDTO);
//            RabbitMqSend.SynchSendMessage(s);


//            String dish = restTemplate.delete(String.valueOf(aLong), IndexCoordinates.of("dish"));
//            System.out.println(dish);
//            ByQueryResponse dish = restTemplate.delete(
//                    new NativeSearchQueryBuilder().withQuery(QueryBuilders.termQuery(id, aLong)).build(),//查询条件
//                    DishDTO.class, IndexCoordinates.of("dish"));
//            System.out.println(dish);


            //检查是否有对应的口味信息
            List<DishFlavorEntity> dishFlavorEntityList = dishFlavorEntityMapper.queryDishFlavorByDishId(aLong);
            if (dishFlavorEntityList != null&&dishFlavorEntityList.size()!=0) {
                int size = dishFlavorEntityList.size();
                AssertUtil.isTrue(dishFlavorEntityMapper.deleteByDishId(aLong) != size, 303, "删除失败");
            }
        }

    }

    /**
     * 表关联，多条件动态查询
     *
     * @param dishDTO
     * @return
     */
    public Result<List<DishDTO>> queryDishByAll(DishDTO dishDTO) {
        //准备一个结果集
        Result<List<DishDTO>> dishDTOResult = new Result<>();
        //准备DishDTO数据集
        //注意dishiDto内含口味信息对象，所以应该单独查
        List<DishDTO> dishDTOList = dishEntityMapper.queryDishByAll(dishDTO);


        //单独查询口味信息：遍历查到的结果，把口味信息封装
        for (DishDTO dto : dishDTOList) {
            //根据id获取口味信息
            Long id = dto.getId();
            List<DishFlavorEntity> dishFlavorEntity = dishFlavorEntityMapper.queryDishFlavorByDishId(id);
            //如果存在口味信息就封装
            if (dishFlavorEntity != null) {
                //把集合封装进对象
                dto.setFlavors(dishFlavorEntity);
            }
        }
        //封装进result
        dishDTOResult.setData(dishDTOList);
        return dishDTOResult;
    }

    /**
     * 根据id 查询
     *
     * @param id
     * @return
     */
    public Result<DishDTO> queryDishById(String id) {
        //准备结果集
        Result<DishDTO> dishDTOResult = new Result<>();

        //查询数据库
        DishDTO dishDTO = dishEntityMapper.queryDishById(Long.valueOf(id));

        //添加口味
        List<DishFlavorEntity> dishFlavorEntityList = dishFlavorEntityMapper.queryDishFlavorByDishId(Long.valueOf(id));
        if (dishFlavorEntityList != null &&dishFlavorEntityList.size()!=0) {
            dishDTO.setFlavors(dishFlavorEntityList);
        }
        dishDTOResult.setData(dishDTO);

        return dishDTOResult;

    }






    /**
     * 分页查询
     *
     * @param limit1
     * @param page1
     * @param order1
     * @param orderField1
     * @return
     */
    public Result<PageInfo<DishEntity>> getDishList(Integer limit1, Integer page1, String order1, String orderField1 ,String name) {

        //校验参数
        Integer limit;
        Integer page;
        String order;
        String orderField;
        //校验并设置默认值
        limit = (limit1 != null) ? limit1 : 10;//默认10
        page = (page1 != null) ? page1 : 1;//默认第1页
        order = (StringUtils.isBlank(order1)) ? "asc" : order1;//默认
        orderField = (StringUtils.isBlank(orderField1)) ? "name" : orderField1;//默认排序字段
        //开启分页
        PageHelper.startPage(page, limit);

        //查询list数据集
        List<DishEntity> dishEntityList = dishEntityMapper.queryAll(order, orderField,name);
        //封装list集合
        PageInfo<DishEntity> dishEntityPageInfo = new PageInfo<>(dishEntityList);
        //生成结果集
        Result<PageInfo<DishEntity>> pageInfoResult = new Result<>();
        pageInfoResult.setData(dishEntityPageInfo);

        //返回结果集
        return pageInfoResult;

    }

    public void upDateStatus(List<String> ids) {
        AssertUtil.isTrue(ids == null&& ids.size()==0,302,"你输入的信息不存在");
        for (String id : ids) {
            DishEntity dishEntity = new DishEntity();
            dishEntity.setId(Long.valueOf(id));
            DishDTO dishDTO = dishEntityMapper.queryDishById(Long.valueOf(id));
            AssertUtils.isNull(dishDTO,302,"你输入的信息不存在");
            dishEntity.setStatus(dishDTO.getStatus()==1?0:1);
            //执行更新
            AssertUtil.isTrue(dishEntityMapper.updateStatus(dishEntity)!=1,303,"更新状态失败"

);
        }
    }
}
